package student.aistar.day15.syn;

/**
 * 可见性 - volatile
 *      保证 -> 多个线程访问同一个资源时, 这个资源的状态, 信息等对于其他县城都是可见的.
 *
 *      Java内存模型规定 所有的变量都存储在主内存中, 包括实例变量[类中的非静态属性], 静态变量,
 *      但是不包括局部变量和方法和方法参数.
 *      每个线程都有自己的工作内存, 现成的工作内存保存了该线程用到的变量和主内存的副本拷贝,
 *      县城对变量的操作都在工作内存中进行, 县城不能直接读写主内存中得变量
 *
 */
public class VisibilityDemo {
    //实例变量 - 主内存中存在得
    //强制让程序遵守"缓存一致性协议", 如果主存中的变量一旦发生了改变
    //线程就会强制从主存中重写拷贝这个最新的数据到自己的本地工作内存中去
    private int x;

    //写
    public void writeX(){
        x = 5;
    }

    public void readX(){
        while (x != 5){
            //写线程过了许久之后, x = 5得改变刷回到主存
            //但是读线程在执行循环 - 循环体中出现了同步代码块 - 遇到synchronied
            //一旦遇到了synchronized - 尝试去获取锁资源 - 会清空本地工作内存
            //继续循环又会使用到x, 由于本地工作内存清空了呀, 所以读线程只能到主存中去强制再去拷贝一份x得变量到本地内存
            //拿到的肯定是写线程已经更新之后的那个值x = 5;



            //然后加上这条输出语句或者锁语句, sout底层遇到synchronized锁, 会释放缓存中得资源
            //System.out.println(1);
//            synchronized (this){}
        }
        if(x == 5){
            System.out.println("=======stop=========");
        }
    }

    public static void main(String[] args) {
        VisibilityDemo vd = new VisibilityDemo();
        //创建一个写线程
        Thread t1 = new Thread(()->{
            vd.writeX();
        });

        //创建一个读的线程
        Thread t2 = new Thread(()->{
            vd.readX();
        });

        //线程的执行顺序和你先启动哪个是无关的
        //大部分得场景是 - 概率更高 - 先启动哪个线程, 哪个线程优先执行的机会更大

        //如果先写后读
//        t1.start();
//
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//
//        t2.start();

        //如果先读后写
        t2.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.start();
    }
}
